package com.xiaomaoguai.fcp.pre.plouto.mailbox.autoconfigure;

import com.dh.mailbox2.api.Actor;
import com.dh.mailbox2.disruptormailbox.DisruptorMailBox;
import com.xiaomaoguai.fcp.pre.plouto.mailbox.IMailBox;
import com.xiaomaoguai.fcp.pre.plouto.mailbox.MailBoxesEnums;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * @fileName: AbstractMailBoxRegister.java
 * @author: WeiHui
 * @date: 2018/11/5 21:02
 * @version: v1.0.0
 * @since JDK 1.8
 */
@Slf4j
public abstract class AbstractMailBoxRegister implements MailBoxRegister {

	private List<IMailBox> mailBoxSet = new ArrayList<>();

	@Autowired
	private ApplicationContext applicationContext;

	/**
	 * 初始化方法
	 */
	public void init() {
		register(MailBoxesEnums.values());
		register(register());
	}

	/**
	 * 注册mailBox 进 mailBox 集合
	 *
	 * @param mailBoxes mailBox集合
	 */
	private void register(IMailBox[] mailBoxes) {
		Arrays.stream(mailBoxes).forEach(b -> {
			if (mailBoxSet.contains(b)) {
				log.error("注意：：覆盖之前相同的actor,请检查:当前actor:{}", b);
			}
			mailBoxSet.add(b);
		});
		injectBean(Arrays.asList(mailBoxes));
	}

	/**
	 * 注入bean
	 *
	 * @param mailBoxes 邮箱
	 */
	private void injectBean(List<IMailBox> mailBoxes) {
		ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext;
		DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();

		for (IMailBox mailBox : mailBoxes) {
			Class<? extends Actor> clazz = mailBox.getClazz();
			String actorName = clazz.getSimpleName();
			Actor actor = beanFactory.getBean(clazz);

			BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(DisruptorMailBox.class);
			beanDefinitionBuilder.addPropertyValue("actor", actor);
			beanDefinitionBuilder.addPropertyValue("bufferSize", mailBox.getBufferSize());
			beanDefinitionBuilder.addPropertyValue("nThreads", mailBox.getThreadSize());

			beanFactory.registerBeanDefinition(actorName, beanDefinitionBuilder.getBeanDefinition());
			log.info("{}注册Actor成功,名称为{}", clazz, actorName);
		}
	}

	public List<IMailBox> getMailBoxSet() {
		return Collections.unmodifiableList(mailBoxSet);
	}
}
